﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Modules.Attachment;
using Modules.BankSpecialAccount;
using Modules.Project.Entitys;
using Modules.Project.Repositories;
using Pipelines.Sockets.Unofficial.Arenas;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Exceptions;
using static Modules.Project.ProjectConstants;

namespace Modules.Project
{
    [UseDI(ServiceLifetime.Scoped)]
    public class ProjectCompletedService
    {
        private readonly ProjectCompletedRepository repository;
        private readonly ProjectAttachmentService projectAttachmentService;
        private readonly ProjectGuaranteeRefundService projectGuaranteeRefundService;
        private readonly ProjectGuaranteePaymentService projectGuaranteePaymentService;
        private readonly ProjectGuaranteeAccountService projectGuaranteeAccountService;
        private readonly ProjectService projectService;
        private readonly BankSpecialAccountService projectSpecialAccountService;
        private readonly IApplicationContext applicationContext;
        private readonly ILogger logger;

        public ProjectCompletedService(ProjectCompletedRepository repository, ProjectAttachmentService projectAttachmentService, ProjectGuaranteeRefundService projectGuaranteeRefundService, ProjectGuaranteePaymentService projectGuaranteePaymentService, ProjectGuaranteeAccountService projectGuaranteeAccountService, ProjectService projectService, BankSpecialAccountService projectSpecialAccountService, IApplicationContext applicationContext, ILogger<ProjectCompletedService> logger)
        {
            this.repository = repository;
            this.projectAttachmentService = projectAttachmentService;
            this.projectGuaranteeRefundService = projectGuaranteeRefundService;
            this.projectGuaranteePaymentService = projectGuaranteePaymentService;
            this.projectGuaranteeAccountService = projectGuaranteeAccountService;
            this.projectService = projectService;
            this.projectSpecialAccountService = projectSpecialAccountService;
            this.applicationContext = applicationContext;
            this.logger = logger;
        }

        public ProjectCompleted? GetProjectCompleted(int id)
        {
            return repository.Get(id);
        }

        public IEnumerable<ProjectCompleted> GetProjectCompleteds(IEnumerable<int> ids)
        {
            return repository.PopulateEntitiesByEntityIds(ids);
        }

        public void Create(ProjectCompleted entity, Dictionary<附件类型, List<AttachmentsForm<int>>> dicAttachments)
        {
            try
            {
                applicationContext.Transaction.Begin();

                var payment = projectGuaranteePaymentService.GetProjectGuaranteePaymentByProjectId(entity.ProjectId);
                if (payment != null && payment.GuaranteeAccountType == 保证金类型.保证金账户)
                {
                    entity.RefundableAmount = payment.Paid;
                }

                #region 申请专户销户

                var projectSpecialAccount = projectSpecialAccountService.GetProjectSpecialAccountByProjectId(entity.ProjectId).Where(i => i.AccountStatus == BankSpecialAccountConstants.专户状态.正常).FirstOrDefault();
                if (projectSpecialAccount != null)
                {
                    projectSpecialAccount.AccountStatus = BankSpecialAccountConstants.专户状态.注销申请中;
                    projectSpecialAccountService.UpdateProjectSpecialAccount(projectSpecialAccount);
                    entity.AccountId = projectSpecialAccount.Id;
                }

                #endregion 申请专户销户

                #region 附件

                foreach (var dic in dicAttachments)
                {
                    foreach (var item in dic.Value)
                    {
                        ProjectAttachment projectAttachment = new()
                        {
                            Id = Guid.NewGuid().ToString().Replace("-", ""),
                            AttachmentId = item.AttachmentId,
                            ObjectId = entity.Id.ToString(),
                            Tenant = 项目附件租户.ProjectCompleted,
                            AttachmentType = dic.Key,
                            CreateTime = DateTime.Now
                        };
                        projectAttachmentService.Create(projectAttachment);
                    }
                }

                #endregion 附件

                repository.Insert(entity);

                applicationContext.Transaction.Complete();
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();
                logger.LogError(ex, $"创建完工销户申请失败");
                throw new BusinessException("创建完工销户申请失败,原因:" + ex.Message);
            }
        }

        public void Update(ProjectCompleted entity, Dictionary<附件类型, List<AttachmentsForm<int>>> dicAttachments)
        {
            try
            {
                applicationContext.Transaction.Begin();
                repository.Update(entity);

                #region 附件

                if (dicAttachments.Count() > 0)
                {
                    List<ProjectAttachment> projectAttachments = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(entity.Id, 项目附件租户.ProjectCompleted).ToList();
                    projectAttachmentService.Deleted(projectAttachments.Select(i => i.Id));
                    foreach (var dic in dicAttachments)
                    {
                        foreach (var item in dic.Value)
                        {
                            ProjectAttachment projectAttachment = new()
                            {
                                Id = Guid.NewGuid().ToString().Replace("-", ""),
                                AttachmentId = item.AttachmentId,
                                ObjectId = entity.Id.ToString(),
                                Tenant = 项目附件租户.ProjectCompleted,
                                AttachmentType = dic.Key,
                                CreateTime = DateTime.Now
                            };
                            projectAttachmentService.Create(projectAttachment);
                        }
                    }
                }

                #endregion 附件

                applicationContext.Transaction.Complete();
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();
                logger.LogError(ex, $"修改完工销户申请失败");
                throw new BusinessException("修改完工销户申请失败,原因:" + ex.Message);
            }
        }

        public void Update(ProjectCompleted entity)
        {
            repository.Update(entity);
        }

        /// <summary>
        /// 审核失败
        /// </summary>
        /// <param name="entity"></param>
        /// <exception cref="BusinessException"></exception>
        public void AuditFail(ProjectCompleted entity)
        {
            try
            {
                applicationContext.Transaction.Begin();
                var projectSpecialAccount = projectSpecialAccountService.GetProjectSpecialAccount(entity.AccountId);
                if (projectSpecialAccount != null)
                {
                    projectSpecialAccount.AccountStatus = BankSpecialAccountConstants.专户状态.正常;
                    projectSpecialAccountService.UpdateProjectSpecialAccount(projectSpecialAccount);
                }
                repository.Update(entity);
                applicationContext.Transaction.Complete();
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();
                logger.LogError(ex, $"审核完工销户申请失败");
                throw new BusinessException("审核完工销户申请失败,原因:" + ex.Message);
            }
        }

        /// <summary>
        /// 审核成功
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="refundOrganization"></param>
        /// <param name="refundOrganizationCode"></param>
        /// <exception cref="BusinessException"></exception>
        public void Audit(ProjectCompleted entity, string refundOrganization, string refundOrganizationCode)
        {
            try
            {
                applicationContext.Transaction.Begin();

                var projectSpecialAccount = projectSpecialAccountService.GetProjectSpecialAccount(entity.AccountId);
                if (projectSpecialAccount != null)
                {
                    projectSpecialAccount.CancelReason = entity.ApplyReason;
                    projectSpecialAccount.AccountStatus = BankSpecialAccountConstants.专户状态.待注销;
                    projectSpecialAccountService.UpdateProjectSpecialAccount(projectSpecialAccount);
                }
                entity.EndDate = DateTime.Now;
                repository.Update(entity);

                #region 创建退还保证金记录

                var guaranteePayment = projectGuaranteePaymentService.GetProjectGuaranteePaymentByProjectId(entity.ProjectId);
                if (guaranteePayment != null)
                {
                    entity.GuaranteePaymentId = guaranteePayment.Id;
                    var projectGuaranteeAccount = projectGuaranteeAccountService.GetProjectGuaranteeAccount(guaranteePayment.GuaranteeAccountId);
                    if (guaranteePayment.GuaranteeAccountType == 保证金类型.保证金账户)
                    {
                        //添加保证金退还记录
                        ProjectGuaranteeRefund projectGuaranteeRefund = projectGuaranteeRefundService.GetProjectGuaranteeRefundByGuaranteePaymentId(guaranteePayment.Id)??new ProjectGuaranteeRefund();
                        projectGuaranteeRefund.RefundAmount = entity.RefundAmount;
                        projectGuaranteeRefund.ApplyReason = entity.ApplyReason;
                        projectGuaranteeRefund.RefundReason = entity.RefundReason;
                        projectGuaranteeRefund.RefundTime = DateTime.Now;
                        projectGuaranteeRefund.CreateTime = DateTime.Now;
                        projectGuaranteeRefund.ProjectId = entity.ProjectId;
                        projectGuaranteeRefund.Status = 保证金退还状态.已退还;
                        projectGuaranteeRefund.RefundOrganization = refundOrganization;
                        projectGuaranteeRefund.RefundOrganizationCode = refundOrganizationCode;
                        projectGuaranteeRefund.PaymentName = guaranteePayment.PaymentName;
                        projectGuaranteeRefund.GuaranteePaymentId = guaranteePayment.Id;
                        projectGuaranteeRefund.PaymentCode = guaranteePayment.PaymentCode;
                        projectGuaranteeRefund.ApplyAmount = guaranteePayment.Paid;
                        if (projectGuaranteeRefund.Id > 0)
                        {
                            projectGuaranteeRefundService.Update(projectGuaranteeRefund);
                        }
                        else { 
                        projectGuaranteeRefundService.Create(projectGuaranteeRefund);
                        }
                        //修改缴纳记录
                        guaranteePayment.HasReturn = true;
                        projectGuaranteePaymentService.Update(guaranteePayment);
                    }
                }

                #endregion 创建退还保证金记录

                projectService.UpdateProjectStatus(entity.ProjectId, 项目状态.完工, null, entity.EndDate);

                applicationContext.Transaction.Complete();
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();
                logger.LogError(ex, $"审核完工销户申请失败");
                throw new BusinessException("审核完工销户申请失败,原因:" + ex.Message);
            }
        }

        public bool ExistsByProjectId(int projectId)
        {
            return repository.ExistsByProjectId(projectId);
        }

        public IPagedList<ProjectCompleted> GetProjectCompleteds(ProjectCompletedQuery query, int pageIndex, int pageSize)
        {
            return repository.GetProjectCompleteds(query, pageIndex, pageSize);
        }

        public void Delete(int id)
        {
            var entity = GetProjectCompleted(id) ?? throw new BusinessException("完工销户申请不存在");
            try
            {
                applicationContext.Transaction.Begin();
                var projectSpecialAccount = projectSpecialAccountService.GetProjectSpecialAccount(entity.AccountId);
                if (projectSpecialAccount != null)
                {
                    projectSpecialAccount.AccountStatus = BankSpecialAccountConstants.专户状态.正常;
                    projectSpecialAccountService.UpdateProjectSpecialAccount(projectSpecialAccount);
                }
                repository.DeleteByEntityId(id);
                applicationContext.Transaction.Complete();
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();
                logger.LogError(ex, $"审核完工销户删除失败");
                throw new BusinessException("审核完工销户删除失败,原因:" + ex.Message);
            }
        }

        public void Deleted(IEnumerable<int> ids)
        {
            foreach (int id in ids)
            {
                Delete(id);
            }
        }
    }
}